﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DXBase.Structs
{
	/// <summary>
	/// This is used to represent the viewing area. It also represent 4 sided pyramid truncated at the top.
	/// </summary>
	public struct Frustum
	{
		public Plane3D[] Planes;

		public static Frustum operator*(Matrix4x4F m, Frustum f)
		{
			var result = new Frustum { Planes = new Plane3D[f.Planes.Length] };
			for (int i = 0; i < f.Planes.Length; i++)
				result.Planes[i] = m * f.Planes[i];
			return result;
		}

		/// <summary>
		/// This test intersection with a Box3D. It might give a few false positive for box close to the frustrum's edges.
		/// </summary>
		public bool Intersects(Box3D box) { return Intersects(box.GetVertices()); }
		/// <summary>
		/// This test intersection with a Box3D. It might give a few false positive for box close to the frustrum's edges.
		/// </summary>
		public bool Intersects(IEnumerable<Vector3F> shapesVertices)
		{
			foreach (var plane in Planes)
			{
				bool behind = false;
				foreach (var v in shapesVertices)
				{
					float pos = plane.Normal * v;
					if (pos <= plane.Value)
					{
						behind = true;
						break;
					}
				}
				// all points are on the outside side of this plane
				if (!behind)
					return false;
			}
			return true;
		}

		public override string ToString()
		{
			var sb = new StringBuilder();
			sb.Append("Frustrum(");
			if (Planes != null)
				for (int i = 0; i < Planes.Length; i++)
				{
					if (i > 0) sb.Append(", ");
					sb.Append(Planes[i]);
				}
			sb.Append(")");
			return sb.ToString();
		}
	}
}
